//
//  ApplePayManager.swift
//  LeTu
//
//  Created by gy on 2024/1/4.
//

import Foundation
import StoreKit
import CoreData

class ApplePayManager: NSObject {
    
    static let shared = ApplePayManager()
    
    private(set) var paySuccess: (() -> Void)?
    private(set) var requestProductSuccess: (() -> Void)?
    private(set) var payFailure: (() -> Void)?
    private(set) var purchaseType: Int64 = 0
    private(set) var orderMoney: Float = 0
    
    lazy var context: NSManagedObjectContext = {
        let context = ((UIApplication.shared.delegate) as! AppDelegate).persistentContainer.viewContext
        return context
    }()
    
    // 更新数据
    private func saveContext() {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
    
    override private init() {
        super.init()
        SKPaymentQueue.default().add(self)
    }
    
    func requesProductInfo(productId: String, purchaseType: Int64, orderMoney: Float, success: @escaping () -> Void, requestProductSuccess: @escaping () -> Void, failure: @escaping () -> Void) {
        
        self.paySuccess = success
        self.requestProductSuccess = requestProductSuccess
        self.payFailure = failure
        self.purchaseType = purchaseType
        self.orderMoney = orderMoney
        
        guard SKPaymentQueue.canMakePayments(), productId.count > 0 else {
            MYLog("用户不允许进行内购或者未提供产品标识符")
            payFailure?()
            return
        }
        
        let productsRequest = SKProductsRequest(productIdentifiers: [productId])
        productsRequest.delegate = self
        productsRequest.start()
    }
    
    /// 恢复购买
    func restore() {
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
    
    private func completeTransaction(_ transaction: SKPaymentTransaction) {
        guard transaction.transactionState == .purchased || transaction.transactionState == .restored else {
            MYLog("交易状态不正确")
            ApplePayManager.shared.payFailure?()
            return
        }
        
        SKPaymentQueue.default().finishTransaction(transaction)
        
        var transactionId: String?
        if let originalTransaction = transaction.original {
            transactionId = originalTransaction.transactionIdentifier
        } else {
            transactionId = transaction.transactionIdentifier
        }
        
        guard let receiptJson = vertifyReceipt(), let transactionId = transactionId else {
            MYLog("凭证校验失败")
            ApplePayManager.shared.payFailure?()
            return
        }
        requestServiceVertifyReceipt(receiptJson: receiptJson, transactionID: transactionId, purchaseType: purchaseType, orderMoney: orderMoney)
        
    }
    
    /// 服务器验证凭据
    private func requestServiceVertifyReceipt(receiptJson: String, transactionID: String, purchaseType: Int64, orderMoney: Float) {
        
        let params: [String: Any] = ["receipt": receiptJson, "TransactionID": transactionID, "purchaseType": purchaseType, "orderMoney": orderMoney]
        apiProvider.request(api: .applePay(params: params)) { json, jsonArr, code in
            MYLog(json, code)
            // 处理上传结果
            guard let pm = Mapper<ResponseModel>().map(JSON: json), code == 200, pm.code == 200 else {
                ApplePayManager.shared.payFailure?()
                return
            }
            MYLog("交易成功")
            ApplePayManager.shared.paySuccess?()
        } failureHandler: { error in
            // 处理上传失败
            ApplePayManager.shared.payFailure?()
            DispatchQueue.main.async {
                self.saveConfigContext(receipt: receiptJson, transactionId: transactionID)
            }
        }
    }
    
    private func vertifyReceipt() -> String? {
        guard let receiptURL = Bundle.main.appStoreReceiptURL,
              let receiptData = try? Data(contentsOf: receiptURL) else {
            return nil
        }
        return receiptData.base64EncodedString(options: .endLineWithLineFeed)
    }
    
}

// MARK: - 处理未完成的交易
extension ApplePayManager {
    
    // 在应用启动时恢复未完成的交易
    func restoreTransactions() {
        
        guard kUserManager.isLogin else { return }
        
        handleTransaction(SKPaymentQueue.default().transactions)
        
        let receipts = getAllReceiptData()
        for receipt in receipts {
            if let receiptJson = receipt.receipt, let transId = receipt.transactionId, receipt.userId == kUserManager.userModel.id {
                requestServiceVertifyReceipt(receiptJson: receiptJson, transactionID: transId, purchaseType: receipt.purchaseType, orderMoney: receipt.orderMoney)
            }
        }
    }
    
    private func handleTransaction(_ transactions: [SKPaymentTransaction]) {
        
        for transaction in transactions {
            
            switch transaction.transactionState {
            case .purchased, .restored:
                // 处理交易成功或恢复成功的情况
                completeTransaction(transaction)
            case .failed:
                // 处理交易失败的情况
                SKPaymentQueue.default().finishTransaction(transaction)
                ApplePayManager.shared.payFailure?()
            case .purchasing:
                // 正在交易，不需要处理
                ApplePayManager.shared.requestProductSuccess?()
                break
            case .deferred:
                // 交易延迟，不需要处理
                break
            @unknown default:
                break
            }
        }
        
    }
    
}

// MARK: - 缓存凭证
extension ApplePayManager {
    
    // 获取缓存信息
    func getAllReceiptData() -> [LTPayment] {
        let fetchRequest: NSFetchRequest = LTPayment.fetchRequest()
        do {
            let result = try context.fetch(fetchRequest)
            return result
        } catch {
            fatalError()
        }
    }
    
    // 查找某条数据
    func searchReceiptData(transactionId: String) -> LTPayment? {
        let configs = getAllReceiptData()
        for config in configs {
            if config.transactionId == transactionId {
                return config
            }
        }
        return nil
    }
    
    // 保存数据
    func saveConfigContext(receipt: String, transactionId: String) {
        
        let deviceConfig: LTPayment?

        if let devConfig = searchReceiptData(transactionId: transactionId) {
            deviceConfig = devConfig
        } else {
            deviceConfig = NSEntityDescription.insertNewObject(forEntityName: "LTPayment", into: context) as? LTPayment
        }
        
        guard let devConfig = deviceConfig else { return }
        devConfig.receipt = receipt
        devConfig.transactionId = transactionId
        devConfig.userId = Int64(kUserManager.userModel.id)
        devConfig.purchaseType = purchaseType
        devConfig.orderMoney = orderMoney
        saveContext()
        
    }
    
    // 删除全部数据
    func deleteDevConfihCacheData() {
        let result = getAllReceiptData()
        for config in result {
            context.delete(config)
        }
        saveContext()
    }
    
}


// MARK: - SKPaymentQueueDelegate
extension ApplePayManager: SKPaymentQueueDelegate {
    
    func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool {
        // 在这里处理外部购买请求
        // 返回 true 表示允许处理此购买请求，返回 false 表示拒绝处理此购买请求
        return true
    }
    
}

// MARK: - SKProductsRequestDelegate
extension ApplePayManager: SKProductsRequestDelegate {
    
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
                
        guard !response.products.isEmpty else {
            MYLog("未找到商品信息")
            ApplePayManager.shared.payFailure?()
            return
        }
        
        if !response.invalidProductIdentifiers.isEmpty {
            MYLog("商品请求错误,error: \(response.invalidProductIdentifiers)")
            ApplePayManager.shared.payFailure?()
        }
        
        guard let product = response.products.first else {
            ApplePayManager.shared.payFailure?()
            return
        }
        MYLog("商品详情: \(product.description)")
        MYLog("商品价格: \(product.price)")
        MYLog("商品名字: \(product.productIdentifier)")
        
        let payment = SKPayment(product: product)
        SKPaymentQueue.default().add(payment)
    }
    
    func request(_ request: SKRequest, didFailWithError error: Error) {
        MYLog("请求失败: \(error.localizedDescription)")
        ApplePayManager.shared.payFailure?()
    }
    
}

// MARK: - SKPaymentTransactionObserver
extension ApplePayManager: SKPaymentTransactionObserver {
    
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        handleTransaction(transactions)
    }
    
}
